In this notebook we are doing a quick exploration of the use of storing spatial data in a SpatialExperiment object or in a Seurat object. We will take a look at one library, SCPCR000372, that has been quantified with Spaceranger and compare the use of SpatialExperiment to Seurat.

Set Up

library(magrittr)
Warning message:
package ‘GenomicRanges’ was built under R version 4.1.2 
library(ggplot2)
library(SingleCellExperiment)
library(SpatialExperiment)
# load in benchmarking functions that will be used for copying data and generating sample tables
function_path <- file.path(".." ,"benchmarking-functions", "R")
file.path(function_path, list.files(function_path, pattern = "*.R$")) %>%
  purrr::walk(source)
# set up file paths 
base_dir <- here::here()

# output folder to store alevin-fry and spaceranger quants from S3
data_dir <- file.path(base_dir, "data", "spatial") 
s3_out <- file.path(data_dir, "data", "quants")

# results directory 
results_dir <- file.path(data_dir, "results")

# create directories
if(!dir.exists(data_dir)){
  dir.create(data_dir, recursive = TRUE)
}

if(!dir.exists(results_dir)){
  dir.create(results_dir, recursive = TRUE)
}
mito_file <- file.path(base_dir, "sample-info", "Homo_sapiens.GRCh38.103.mitogenes.txt")
  
# read in mito genes 
mito_genes <- readr::read_tsv(mito_file, col_names = "gene_id")
Rows: 111 Columns: 1
── Column specification ───────────────────────────────────────────
Delimiter: "\t"
chr (1): gene_id

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
mito_genes <- mito_genes %>%
  dplyr::pull(gene_id) %>%
  unique()

Copy data from S3

# set samples to process
sample_id <- c("SCPCR000372")
# download alevin fry and cellranger output
aws_copy_samples(local_dir = s3_out,
                 s3_dir = "s3://nextflow-ccdl-results/scpca",
                 samples = sample_id,
                 tools = c("alevin-fry-knee", "cellranger"))

Comparing SpatialExperiment to Seurat

Importing Alevin-fry and Spaceranger output into a SpatialExperiment

First we are testing use of a SpatialExperiment object to store the spatial transcriptomics results. We will look at the Alevin-fry + Spaceranger quantification and use a custom function to create the combined object from both tools.

# get path to fry output directory 
fry_dir <- file.path(s3_out, "alevin-fry-knee", sample_id)
fry_dir <- paste0(fry_dir, "-spliced_intron_txome_k31-salign-cr-like-em-knee")

# paths to spatial folders 
cellranger_folder <- paste0(sample_id, "-cdna-spatial")
spatial_dir <- file.path(s3_out, "cellranger", cellranger_folder, "outs", "spatial")
# read in combined fry and spaceranger spe 
fry_spe <- create_fry_spaceranger_spe(fry_dir, 
                                       spatial_dir, 
                                       sample_id)
Rows: 4992 Columns: 6
── Column specification ───────────────────────────────────────────
Delimiter: ","
chr (1): barcode
dbl (5): in_tissue, array_row, array_col, pxl_row_in_fullres, p...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Joining, by = "barcode"
Found more than one class "SpatialImage" in cache; using the first, from namespace 'SpatialExperiment'
Also defined by ‘SeuratObject’

Importing as Seurat Object

Below we will import the same data but as a Seurat object instead of a SpatialExperiment object.

# first create sce from Alevin output
fry_sce <- scpcaTools::read_alevin(fry_dir,
                                   usa_mode = TRUE,
                                   which_counts = "spliced")

# convert sce to seurat object 
fry_seurat <- Seurat::CreateSeuratObject(counts = counts(fry_sce),
                                 project = "SPATIAL",
                                 assay = "Spatial")

# read in image data using Seurat and subset to common cells
image_data <- Seurat::Read10X_Image(spatial_dir)
rownames(image_data@coordinates) <- gsub("-1","", rownames(image_data@coordinates))
common_cells <- intersect(Seurat::Cells(x = fry_seurat), rownames(image_data@coordinates))
image_data <- image_data[common_cells,]

# add image data to Seurat
Seurat::DefaultAssay(object = image_data) <- "Spatial"
fry_seurat[['slice']] <- image_data

Comparing Seurat and Spatial Experiment

Now let’s take a look at how each of these objects stores information for the experiment.

head(colData(fry_spe))
DataFrame with 6 rows and 1 column
                   sample_id
                 <character>
TGGCGATCAAGTTATG SCPCR000372
GCAGGACTATAGAATA SCPCR000372
CCATCGCAGTTAAACT SCPCR000372
TAGCTCGCCTGATAAC SCPCR000372
GATAGGTAACGTTGAC SCPCR000372
GGGAGTAATGGCTGGC SCPCR000372
head(fry_seurat@meta.data)

Seurat automatically adds some per cell QC metrics here, but in general the colData looks similar to what we would expect for a SingleCellExperiment for the SpatialExperiment.

head(rowData(fry_spe))
DataFrame with 6 rows and 0 columns
head(fry_seurat[["Spatial"]]@meta.features)

It looks like both of these start off with no rowData as expected.

fry_spe <- fry_spe %>%
  scuttle::addPerCellQCMetrics(subsets = list(mito_genes = mito_genes[mito_genes %in% rownames(fry_spe)])) 
Found more than one class "SpatialImage" in cache; using the first, from namespace 'SpatialExperiment'
Also defined by ‘SeuratObject’
Found more than one class "SpatialImage" in cache; using the first, from namespace 'SpatialExperiment'
Also defined by ‘SeuratObject’
head(colData(fry_spe))
DataFrame with 6 rows and 7 columns
                   sample_id       sum  detected
                 <character> <numeric> <integer>
TGGCGATCAAGTTATG SCPCR000372   16606.1      5342
GCAGGACTATAGAATA SCPCR000372   16574.8      5812
CCATCGCAGTTAAACT SCPCR000372   16978.9      5806
TAGCTCGCCTGATAAC SCPCR000372   16631.1      5669
GATAGGTAACGTTGAC SCPCR000372   17316.3      5830
GGGAGTAATGGCTGGC SCPCR000372   15565.1      5192
                 subsets_mito_genes_sum
                              <numeric>
TGGCGATCAAGTTATG                240.298
GCAGGACTATAGAATA                225.685
CCATCGCAGTTAAACT                450.882
TAGCTCGCCTGATAAC                334.209
GATAGGTAACGTTGAC                265.890
GGGAGTAATGGCTGGC                393.000
                 subsets_mito_genes_detected
                                   <integer>
TGGCGATCAAGTTATG                          12
GCAGGACTATAGAATA                          12
CCATCGCAGTTAAACT                          12
TAGCTCGCCTGATAAC                          11
GATAGGTAACGTTGAC                          11
GGGAGTAATGGCTGGC                          12
                 subsets_mito_genes_percent     total
                                  <numeric> <numeric>
TGGCGATCAAGTTATG                    1.44705   16606.1
GCAGGACTATAGAATA                    1.36162   16574.8
CCATCGCAGTTAAACT                    2.65555   16978.9
TAGCTCGCCTGATAAC                    2.00954   16631.1
GATAGGTAACGTTGAC                    1.53549   17316.3
GGGAGTAATGGCTGGC                    2.52487   15565.1

You can still use the same functions to add in per cell metrics that we are using in scpcaTools now on a SpatialExperiment.

Let’s specifically look at how each of them stores the data related to the spatial information. The SpatialExperiment has three places where it stores spatial information, spatialData, spatialCoords, and imgData.

head(spatialData(fry_spe))
DataFrame with 6 rows and 4 columns
           barcode in_tissue array_row array_col
       <character> <numeric> <numeric> <numeric>
1 TGGCGATCAAGTTATG         1        51        55
2 GCAGGACTATAGAATA         1        35        37
3 CCATCGCAGTTAAACT         1        50        62
4 TAGCTCGCCTGATAAC         1        50        58
5 GATAGGTAACGTTGAC         1        48        60
6 GGGAGTAATGGCTGGC         1        10        42
head(spatialCoords(fry_spe))
     pxl_col_in_fullres pxl_row_in_fullres
[1,]               4426               6160
[2,]               3441               4659
[3,]               4805               6063
[4,]               4588               6064
[5,]               4695               5875
[6,]               3695               2302

spatialData holds information about whether or not each barcode was covered by tissue and spatial metadata. spatialCoords holds the coordinates for each spot.

This same information can be found by looking in the images slot in the Seurat object.

head(fry_seurat@images)
$slice
An object of class "VisiumV1"
Slot "image":
, , 1

            [,1]      [,2]      [,3]      [,4]      [,5]      [,6]
  [1,] 0.9294118 0.9239490 0.9239490 0.9239490 0.9294118 0.9294118
            [,7]      [,8]      [,9]     [,10]     [,11]     [,12]
  [1,] 0.9239490 0.9239490 0.9239490 0.9294118 0.9294118 0.9254902
           [,13]     [,14]     [,15]     [,16]     [,17]     [,18]
  [1,] 0.9254902 0.9215686 0.9215686 0.9215686 0.9215686 0.9215686
           [,19]     [,20]     [,21]     [,22]     [,23]     [,24]
  [1,] 0.9161059 0.9121843 0.9082628 0.9121843 0.9027848 0.9027848
           [,25]     [,26]     [,27]     [,28]     [,29]     [,30]
  [1,] 0.9200275 0.9254902 0.9254902 0.9294118 0.9294118 0.9294118
           [,31]     [,32]     [,33]     [,34]     [,35]     [,36]
  [1,] 0.9254902 0.9215686 0.9215686 0.9215686 0.9215686 0.9215686
           [,37]     [,38]     [,39]     [,40]     [,41]     [,42]
  [1,] 0.9161059 0.9161059 0.9161059 0.9215686 0.9215686 0.9215686
           [,43]     [,44]     [,45]     [,46]     [,47]     [,48]
  [1,] 0.9215686 0.9215686 0.9215686 0.9215686 0.9176471 0.9176471
           [,49]     [,50]     [,51]     [,52]     [,53]     [,54]
  [1,] 0.9137255 0.9098039 0.9137255 0.9121843 0.9121843 0.9121843
           [,55]     [,56]     [,57]     [,58]     [,59]     [,60]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471
           [,61]     [,62]     [,63]     [,64]     [,65]     [,66]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471
           [,67]     [,68]     [,69]     [,70]     [,71]     [,72]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471 0.9137255
           [,73]     [,74]     [,75]     [,76]     [,77]     [,78]
  [1,] 0.9137255 0.9137255 0.9137255 0.9137255 0.9121843 0.9176471
           [,79]     [,80]     [,81]     [,82]     [,83]     [,84]
  [1,] 0.9121843 0.9176471 0.9176471 0.9121843 0.9121843 0.9121843
           [,85]     [,86]     [,87]     [,88]     [,89]     [,90]
  [1,] 0.9121843 0.9082628 0.9137255 0.9137255 0.9137255 0.9176471
           [,91]     [,92]     [,93]     [,94]     [,95]     [,96]
  [1,] 0.9176471 0.9176471 0.9176471 0.9121843 0.9082628 0.9137255
           [,97]     [,98]     [,99]    [,100]    [,101]    [,102]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471
          [,103]    [,104]    [,105]    [,106]    [,107]    [,108]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471 0.9082628
          [,109]    [,110]    [,111]    [,112]    [,113]    [,114]
  [1,] 0.9043259 0.9082628 0.9098039 0.9098039 0.9098039 0.9098039
          [,115]    [,116]    [,117]    [,118]    [,119]    [,120]
  [1,] 0.9137255 0.9137255 0.9098039 0.9098039 0.9098039 0.9098039
          [,121]    [,122]    [,123]    [,124]    [,125]    [,126]
  [1,] 0.9098039 0.9137255 0.9137255 0.9137255 0.9137255 0.9098039
          [,127]    [,128]    [,129]    [,130]    [,131]    [,132]
  [1,] 0.9137255 0.9137255 0.9137255 0.9137255 0.9137255 0.9137255
          [,133]    [,134]    [,135]    [,136]    [,137]    [,138]
  [1,] 0.9098039 0.9098039 0.9098039 0.9098039 0.9137255 0.9137255
          [,139]    [,140]    [,141]    [,142]    [,143]    [,144]
  [1,] 0.9137255 0.9137255 0.9176471 0.9215686 0.9215686 0.9254902
          [,145]    [,146]    [,147]    [,148]    [,149]    [,150]
  [1,] 0.9254902 0.9254902 0.9254902 0.9254902 0.9254902 0.9254902
          [,151]    [,152]    [,153]    [,154]    [,155]    [,156]
  [1,] 0.9254902 0.9254902 0.9254902 0.9200275 0.9215686 0.9121843
          [,157]    [,158]    [,159]    [,160]    [,161]    [,162]
  [1,] 0.9176471 0.9176471 0.9215686 0.9215686 0.9215686 0.9215686
          [,163]    [,164]    [,165]    [,166]    [,167]    [,168]
  [1,] 0.9215686 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471
          [,169]    [,170]    [,171]    [,172]    [,173]    [,174]
  [1,] 0.9215686 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471
          [,175]    [,176]    [,177]    [,178]    [,179]    [,180]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471
          [,181]    [,182]    [,183]    [,184]    [,185]    [,186]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471 0.9176471
          [,187]    [,188]    [,189]    [,190]    [,191]    [,192]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9215686 0.9215686
          [,193]    [,194]    [,195]    [,196]    [,197]    [,198]
  [1,] 0.9215686 0.9215686 0.9176471 0.9176471 0.9176471 0.9176471
          [,199]    [,200]    [,201]    [,202]    [,203]    [,204]
  [1,] 0.9176471 0.9176471 0.9176471 0.9176471 0.9215686 0.9215686
          [,205]    [,206]    [,207]    [,208]    [,209]    [,210]
  [1,] 0.9215686 0.9215686 0.9215686 0.9254902 0.9254902 0.9254902
          [,211]    [,212]    [,213]    [,214]    [,215]    [,216]
  [1,] 0.9254902 0.9254902 0.9254902 0.9254902 0.9254902 0.9254902
          [,217]    [,218]    [,219]    [,220]    [,221]    [,222]
  [1,] 0.9254902 0.9200275 0.9254902 0.9254902 0.9254902 0.9254902
          [,223]    [,224]    [,225]    [,226]    [,227]    [,228]
  [1,] 0.9254902 0.9254902 0.9254902 0.9254902 0.9254902 0.9254902
          [,229]    [,230]    [,231]    [,232]    [,233]    [,234]
  [1,] 0.9254902 0.9254902 0.9254902 0.9176471 0.9137255 0.9043259
          [,235]    [,236]    [,237]    [,238]    [,239]    [,240]
  [1,] 0.9098039 0.9098039 0.9137255 0.9137255 0.9137255 0.9098039
          [,241]    [,242]    [,243]    [,244]    [,245]    [,246]
  [1,] 0.9098039 0.9098039 0.9098039 0.9098039 0.9137255 0.9137255
          [,247]    [,248]    [,249]    [,250]    [,251]    [,252]
  [1,] 0.9137255 0.9137255 0.9082628 0.9043259 0.9137255 0.9098039
          [,253]    [,254]    [,255]    [,256]    [,257]    [,258]
  [1,] 0.9098039 0.9137255 0.9137255 0.9137255 0.9098039 0.9098039
          [,259]    [,260]    [,261]    [,262]    [,263]    [,264]
  [1,] 0.9098039 0.9098039 0.9137255 0.9098039 0.9019608 0.9019608
          [,265]    [,266]    [,267]    [,268]    [,269]    [,270]
  [1,] 0.8925612 0.9019608 0.9019608 0.9019608 0.9019608 0.9019608
          [,271]    [,272]    [,273]    [,274]    [,275]    [,276]
  [1,] 0.9019608 0.9019608 0.9019608 0.9019608 0.9019608 0.9019608
          [,277]    [,278]    [,279]    [,280]    [,281]    [,282]
  [1,] 0.9019608 0.9058824 0.9019608 0.9058824 0.9098039 0.9098039
          [,283]    [,284]    [,285]    [,286]    [,287]    [,288]
  [1,] 0.9098039 0.9098039 0.9098039 0.9098039 0.9098039 0.9058824
          [,289]    [,290]    [,291]    [,292]    [,293]    [,294]
  [1,] 0.9058824 0.9058824 0.9098039 0.9098039 0.9098039 0.9098039
          [,295]    [,296]    [,297]    [,298]    [,299]    [,300]
  [1,] 0.9004044 0.9004044 0.9058824 0.9058824 0.9058824 0.9058824
          [,301]    [,302]    [,303]    [,304]    [,305]    [,306]
  [1,] 0.9058824 0.9058824 0.8925612 0.8980392 0.9058824 0.9058824
          [,307]    [,308]    [,309]    [,310]    [,311]    [,312]
  [1,] 0.9058824 0.9058824 0.9058824 0.9058824 0.9004044 0.9058824
          [,313]    [,314]    [,315]    [,316]    [,317]    [,318]
  [1,] 0.9058824 0.9058824 0.9058824 0.9058824 0.9058824 0.9058824
          [,319]    [,320]    [,321]    [,322]    [,323]    [,324]
  [1,] 0.9019608 0.9019608 0.9058824 0.9058824 0.9058824 0.9058824
          [,325]    [,326]    [,327]    [,328]    [,329]    [,330]
  [1,] 0.9058824 0.9004044 0.9058824 0.9058824 0.9058824 0.9058824
          [,331]    [,332]    [,333]    [,334]    [,335]    [,336]
  [1,] 0.9058824 0.9058824 0.9058824 0.9058824 0.9058824 0.9058824
          [,337]    [,338]    [,339]    [,340]    [,341]    [,342]
  [1,] 0.9058824 0.9058824 0.9058824 0.9019608 0.9019608 0.9019608
          [,343]    [,344]    [,345]    [,346]    [,347]    [,348]
  [1,] 0.8980392 0.9019608 0.9019608 0.9019608 0.9019608 0.9019608
          [,349]    [,350]    [,351]    [,352]    [,353]    [,354]
  [1,] 0.9019608 0.8980392 0.8980392 0.8980392 0.8980392 0.9019608
          [,355]    [,356]    [,357]    [,358]    [,359]    [,360]
  [1,] 0.9019608 0.9019608 0.8980392 0.8980392 0.8980392 0.9019608
          [,361]    [,362]    [,363]    [,364]    [,365]    [,366]
  [1,] 0.8980392 0.8980392 0.8980392 0.8980392 0.8980392 0.8980392
          [,367]    [,368]    [,369]    [,370]    [,371]    [,372]
  [1,] 0.8980392 0.8980392 0.8980392 0.9019608 0.9019608 0.9019608
          [,373]    [,374]    [,375]    [,376]    [,377]    [,378]
  [1,] 0.8941176 0.8980392 0.8980392 0.8980392 0.9019608 0.9019608
          [,379]    [,380]    [,381]    [,382]    [,383]    [,384]
  [1,] 0.8980392 0.8980392 0.8980392 0.8980392 0.8980392 0.8980392
          [,385]    [,386]    [,387]    [,388]    [,389]    [,390]
  [1,] 0.9019608 0.8980392 0.9019608 0.8980392 0.8980392 0.8980392
          [,391]    [,392]    [,393]    [,394]    [,395]    [,396]
  [1,] 0.8980392 0.8980392 0.8980392 0.8980392 0.8980392 0.8980392
          [,397]    [,398]    [,399]    [,400]    [,401]    [,402]
  [1,] 0.8980392 0.8980392 0.8980392 0.9019608 0.9019608 0.9019608
          [,403]    [,404]    [,405]    [,406]    [,407]    [,408]
  [1,] 0.9019608 0.9019608 0.9019608 0.8980392 0.8980392 0.9019608
          [,409]    [,410]    [,411]    [,412]    [,413]    [,414]
  [1,] 0.9019608 0.9019608 0.8980392 0.8980392 0.8980392 0.8980392
          [,415]    [,416]    [,417]    [,418]    [,419]    [,420]
  [1,] 0.8980392 0.9019608 0.8980392 0.8980392 0.8941176 0.8941176
          [,421]    [,422]    [,423]    [,424]    [,425]    [,426]
  [1,] 0.8980392 0.8980392 0.8980392 0.8941176 0.8941176 0.8941176
          [,427]    [,428]    [,429]    [,430]    [,431]    [,432]
  [1,] 0.8941176 0.8941176 0.8941176 0.8941176 0.8941176 0.8941176
          [,433]    [,434]    [,435]    [,436]    [,437]    [,438]
  [1,] 0.8980392 0.8941176 0.8941176 0.8941176 0.8980392 0.8980392
          [,439]    [,440]    [,441]    [,442]    [,443]    [,444]
  [1,] 0.8980392 0.8980392 0.8941176 0.8941176 0.8941176 0.8941176
          [,445]    [,446]    [,447]    [,448]    [,449]    [,450]
  [1,] 0.8941176 0.8941176 0.8980392 0.8980392 0.8980392 0.8886397
          [,451]    [,452]    [,453]    [,454]    [,455]    [,456]
  [1,] 0.8941176 0.8941176 0.8980392 0.8980392 0.8980392 0.8980392
          [,457]    [,458]    [,459]    [,460]    [,461]    [,462]
  [1,] 0.8941176 0.8941176 0.8941176 0.8941176 0.8941176 0.8941176
          [,463]    [,464]    [,465]    [,466]    [,467]    [,468]
  [1,] 0.8941176 0.8980392 0.8941176 0.8941176 0.8941176 0.8980392
          [,469]    [,470]    [,471]    [,472]    [,473]    [,474]
  [1,] 0.8980392 0.8980392 0.8941176 0.8941176 0.8941176 0.8941176
          [,475]    [,476]    [,477]    [,478]    [,479]    [,480]
  [1,] 0.8941176 0.8941176 0.8941176 0.8980392 0.9035172 0.8941176
          [,481]    [,482]    [,483]    [,484]    [,485]    [,486]
  [1,] 0.8886397 0.8941176 0.8980392 0.8941176 0.8980392 0.8941176
          [,487]    [,488]    [,489]    [,490]    [,491]    [,492]
  [1,] 0.8941176 0.8941176 0.8941176 0.8941176 0.8941176 0.8941176
          [,493]    [,494]    [,495]    [,496]    [,497]    [,498]
  [1,] 0.8941176 0.8941176 0.8901961 0.8901961 0.8901961 0.8901961
          [,499]    [,500]    [,501]    [,502]    [,503]    [,504]
  [1,] 0.8901961 0.8901961 0.8901961 0.8901961 0.8901961 0.8862745
          [,505]    [,506]    [,507]    [,508]    [,509]    [,510]
  [1,] 0.8901961 0.8901961 0.8901961 0.8901961 0.8823529 0.8705882
          [,511]    [,512]    [,513]    [,514]    [,515]    [,516]
  [1,] 0.8705882 0.8651102 0.8705882 0.8705882 0.8705882 0.8705882
          [,517]    [,518]    [,519]    [,520]    [,521]    [,522]
  [1,] 0.8705882 0.8666667 0.8666667 0.8666667 0.8705882 0.8705882
          [,523]    [,524]    [,525]    [,526]    [,527]    [,528]
  [1,] 0.8705882 0.8705882 0.8705882 0.8705882 0.8705882 0.8705882
          [,529]    [,530]    [,531]    [,532]    [,533]    [,534]
  [1,] 0.8705882 0.8705882 0.8705882 0.8705882 0.8705882 0.8666667
          [,535]    [,536]    [,537]    [,538]    [,539]    [,540]
  [1,] 0.8666667 0.8666667 0.8705882 0.8666667 0.8666667 0.8705882
          [,541]    [,542]    [,543]    [,544]    [,545]    [,546]
  [1,] 0.8705882 0.8666667 0.8666667 0.8705882 0.8705882 0.8705882
          [,547]    [,548]    [,549]    [,550]    [,551]    [,552]
  [1,] 0.8705882 0.8705882 0.8666667 0.8666667 0.8666667 0.8666667
          [,553]    [,554]    [,555]    [,556]    [,557]    [,558]
  [1,] 0.8666667 0.8705882 0.8705882 0.8705882 0.8666667 0.8611887
          [,559]    [,560]    [,561]    [,562]    [,563]    [,564]
  [1,] 0.8666667 0.8611887 0.8611887 0.8651102 0.8651102 0.8666667
          [,565]    [,566]    [,567]    [,568]    [,569]    [,570]
  [1,] 0.8666667 0.8666667 0.8666667 0.8666667 0.8666667 0.8705882
          [,571]    [,572]
  [1,] 0.8705882 0.8941176

 [ reached getOption("max.print") -- omitted 599 row(s) and 2 matrix slice(s) ]

Slot "scale.factors":
$spot
[1] 0.2

$fiducial
[1] 113.7005

$hires
[1] 0.2

$lowres
[1] 0.06

attr(,"class")
[1] "scalefactors"

Slot "coordinates":

Slot "spot.radius":
[1] 0.01137005

Slot "assay":
[1] "Spatial"

Slot "key":
[1] "slice_"

imgData holds information about each image that is stored as multiple slices of an image can be stored within one SpatialExperiment.

imgData(fry_spe)
DataFrame with 1 row and 4 columns
    sample_id    image_id   data scaleFactor
  <character> <character> <list>   <numeric>
1 SCPCR000372      lowres   ####        0.06

This same information can be found by looking at the images slot in the Seurat object.

fry_seurat@images$slice@scale.factors
$spot
[1] 0.2

$fiducial
[1] 113.7005

$hires
[1] 0.2

$lowres
[1] 0.06

attr(,"class")
[1] "scalefactors"

Let’s take a look at some example plots that can be produced with each of these objects.

library(viridis)
Loading required package: viridisLite
# plot tissue spots coloring by total UMI count
ggspavis::plotSpots(spe = fry_spe, 
          x_coord = "pxl_col_in_fullres", 
          y_coord = "pxl_row_in_fullres", 
          annotate = "sum") +
  scale_color_viridis_c()
Scale for 'colour' is already present. Adding another scale for
'colour', which will replace the existing scale.

You can also overlay the image by using plotVisium.

ggspavis::plotVisium(spe = fry_spe[,spatialData(fry_spe)$in_tissue == 1],
                     x_coord = "pxl_col_in_fullres",
                     y_coord = "pxl_row_in_fullres")
Found more than one class "SpatialImage" in cache; using the first, from namespace 'SpatialExperiment'
Also defined by ‘SeuratObject’
Found more than one class "SpatialImage" in cache; using the first, from namespace 'SpatialExperiment'
Also defined by ‘SeuratObject’

Seurat::SpatialFeaturePlot(fry_seurat, features = "nCount_Spatial")
`guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

It looks like overall they both would work and that the SpatialExperiment will provide similar functionality to how we have things already set up for single-cell experiments.

One thing to note is that there is incompatibility between SpatialExperiment and Seurat, and this notebook will not run to completion because of this. The last chunk which includes making the plot using Seurat has a conflict with the imgRaster function present in both Seurat and SpatialExperiment that will cause this chunk to fail. The way to remove this error is to uninstall the SpatialExperiment package and then reinstall Seurat. This is documented in an issue on the Seurat repo.

Additionally, there will be warnings throughout the notebook that both packages refer to SpatialImage, and by default it will always use Seurat, however those chunks will still run. This error appears to occur even without loading Seurat.

sessionInfo()
R version 4.1.1 (2021-08-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.1/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats4    stats     graphics  grDevices utils     datasets 
[7] methods   base     

other attached packages:
 [1] Seurat_4.0.5                SeuratObject_4.0.3         
 [3] SingleCellExperiment_1.16.0 SummarizedExperiment_1.24.0
 [5] Biobase_2.54.0              GenomicRanges_1.46.1       
 [7] GenomeInfoDb_1.30.0         IRanges_2.28.0             
 [9] S4Vectors_0.32.2            BiocGenerics_0.40.0        
[11] MatrixGenerics_1.6.0        matrixStats_0.61.0         

loaded via a namespace (and not attached):
  [1] plyr_1.8.6                igraph_1.2.8             
  [3] lazyeval_0.2.2            splines_4.1.1            
  [5] BiocParallel_1.28.1       listenv_0.8.0            
  [7] scattermore_0.7           ggspavis_1.0.0           
  [9] ggplot2_3.3.5             digest_0.6.28            
 [11] htmltools_0.5.2           magick_2.7.3             
 [13] fansi_0.5.0               magrittr_2.0.1           
 [15] SpatialExperiment_1.3.6   tensor_1.5               
 [17] cluster_2.1.2             ROCR_1.0-11              
 [19] limma_3.50.0              remotes_2.4.1            
 [21] tzdb_0.2.0                globals_0.14.0           
 [23] readr_2.1.0               R.utils_2.11.0           
 [25] spatstat.sparse_2.0-0     prettyunits_1.1.1        
 [27] colorspace_2.0-2          ggrepel_0.9.1            
 [29] xfun_0.28                 dplyr_1.0.7              
 [31] callr_3.7.0               crayon_1.4.2             
 [33] RCurl_1.98-1.5            jsonlite_1.7.2           
 [35] spatstat.data_2.1-0       survival_3.2-13          
 [37] zoo_1.8-9                 glue_1.5.0               
 [39] polyclip_1.10-0           gtable_0.3.0             
 [41] zlibbioc_1.40.0           XVector_0.34.0           
 [43] leiden_0.3.9              DelayedArray_0.20.0      
 [45] pkgbuild_1.2.0            Rhdf5lib_1.16.0          
 [47] DropletUtils_1.14.1       future.apply_1.8.1       
 [49] HDF5Array_1.22.1          abind_1.4-5              
 [51] scales_1.1.1              edgeR_3.36.0             
 [53] DBI_1.1.1                 miniUI_0.1.1.1           
 [55] Rcpp_1.0.7                viridisLite_0.4.0        
 [57] xtable_1.8-4              ggside_0.1.3             
 [59] dqrng_0.3.0               reticulate_1.22          
 [61] spatstat.core_2.3-1       htmlwidgets_1.5.4        
 [63] httr_1.4.2                RColorBrewer_1.1-2       
 [65] ellipsis_0.3.2            ica_1.0-2                
 [67] R.methodsS3_1.8.1         pkgconfig_2.0.3          
 [69] farver_2.1.0              scuttle_1.4.0            
 [71] sass_0.4.0                uwot_0.1.10              
 [73] deldir_1.0-6              locfit_1.5-9.4           
 [75] utf8_1.2.2                here_1.0.1               
 [77] tidyselect_1.1.1          labeling_0.4.2           
 [79] rlang_0.4.12              reshape2_1.4.4           
 [81] later_1.3.0               munsell_0.5.0            
 [83] tools_4.1.1               cli_3.1.0                
 [85] generics_0.1.1            ggridges_0.5.3           
 [87] evaluate_0.14             stringr_1.4.0            
 [89] fastmap_1.1.0             yaml_2.2.1               
 [91] goftest_1.2-3             processx_3.5.2           
 [93] knitr_1.36                fitdistrplus_1.1-6       
 [95] purrr_0.3.4               RANN_2.6.1               
 [97] pbapply_1.5-0             future_1.23.0            
 [99] nlme_3.1-153              sparseMatrixStats_1.6.0  
[101] mime_0.12                 R.oo_1.24.0              
[103] rstudioapi_0.13           compiler_4.1.1           
[105] curl_4.3.2                plotly_4.10.0            
[107] png_0.1-7                 spatstat.utils_2.2-0     
[109] tibble_3.1.6              bslib_0.3.1              
[111] stringi_1.7.5             ps_1.6.0                 
[113] scpcaTools_0.1.2          lattice_0.20-45          
[115] Matrix_1.3-4              vctrs_0.3.8              
[117] rhdf5filters_1.6.0        pillar_1.6.4             
[119] lifecycle_1.0.1           spatstat.geom_2.3-0      
[121] lmtest_0.9-39             jquerylib_0.1.4          
[123] RcppAnnoy_0.0.19          data.table_1.14.2        
[125] cowplot_1.1.1             bitops_1.0-7             
[127] irlba_2.3.3               httpuv_1.6.3             
[129] patchwork_1.1.1           R6_2.5.1                 
[131] promises_1.2.0.1          KernSmooth_2.23-20       
[133] gridExtra_2.3             parallelly_1.29.0        
[135] codetools_0.2-18          MASS_7.3-54              
[137] assertthat_0.2.1          rhdf5_2.38.0             
[139] rjson_0.2.20              rprojroot_2.0.2          
[141] withr_2.4.2               sctransform_0.3.2        
[143] GenomeInfoDbData_1.2.7    mgcv_1.8-38              
[145] parallel_4.1.1            hms_1.1.1                
[147] grid_4.1.1                rpart_4.1-15             
[149] beachmat_2.10.0           tidyr_1.1.4              
[151] rmarkdown_2.11            DelayedMatrixStats_1.16.0
[153] Rtsne_0.15                shiny_1.7.1              
LS0tCnRpdGxlOiAiU3RvcmluZyBTcGF0aWFsIFRyYW5zY3JpcHRvbWljcyBSZXN1bHRzIgphdXRob3I6ICJBbGx5IEhhd2tpbnMgZm9yIENDREwiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKSW4gdGhpcyBub3RlYm9vayB3ZSBhcmUgZG9pbmcgYSBxdWljayBleHBsb3JhdGlvbiBvZiB0aGUgdXNlIG9mIHN0b3Jpbmcgc3BhdGlhbCBkYXRhIGluIGEgW2BTcGF0aWFsRXhwZXJpbWVudGAgb2JqZWN0XShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL3ZpZ25ldHRlcy9TcGF0aWFsRXhwZXJpbWVudC9pbnN0L2RvYy9TcGF0aWFsRXhwZXJpbWVudC5odG1sIzNfQ29tbW9uX29wZXJhdGlvbnMpIG9yIGluIGEgW2BTZXVyYXRgIG9iamVjdF0oaHR0cHM6Ly9zYXRpamFsYWIub3JnL3NldXJhdC9hcnRpY2xlcy9zcGF0aWFsX3ZpZ25ldHRlLmh0bWwpLiAKV2Ugd2lsbCB0YWtlIGEgbG9vayBhdCBvbmUgbGlicmFyeSwgU0NQQ1IwMDAzNzIsIHRoYXQgaGFzIGJlZW4gcXVhbnRpZmllZCB3aXRoIFNwYWNlcmFuZ2VyIGFuZCBjb21wYXJlIHRoZSB1c2Ugb2YgYFNwYXRpYWxFeHBlcmltZW50YCB0byBgU2V1cmF0YC4gIAoKIyMgU2V0IFVwCgpgYGB7cn0KbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQpsaWJyYXJ5KFNwYXRpYWxFeHBlcmltZW50KQpgYGAKCmBgYHtyfQojIGxvYWQgaW4gYmVuY2htYXJraW5nIGZ1bmN0aW9ucyB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgY29weWluZyBkYXRhIGFuZCBnZW5lcmF0aW5nIHNhbXBsZSB0YWJsZXMKZnVuY3Rpb25fcGF0aCA8LSBmaWxlLnBhdGgoIi4uIiAsImJlbmNobWFya2luZy1mdW5jdGlvbnMiLCAiUiIpCmZpbGUucGF0aChmdW5jdGlvbl9wYXRoLCBsaXN0LmZpbGVzKGZ1bmN0aW9uX3BhdGgsIHBhdHRlcm4gPSAiKi5SJCIpKSAlPiUKICBwdXJycjo6d2Fsayhzb3VyY2UpCmBgYAoKYGBge3J9CiMgc2V0IHVwIGZpbGUgcGF0aHMgCmJhc2VfZGlyIDwtIGhlcmU6OmhlcmUoKQoKIyBvdXRwdXQgZm9sZGVyIHRvIHN0b3JlIGFsZXZpbi1mcnkgYW5kIHNwYWNlcmFuZ2VyIHF1YW50cyBmcm9tIFMzCmRhdGFfZGlyIDwtIGZpbGUucGF0aChiYXNlX2RpciwgImRhdGEiLCAic3BhdGlhbCIpIApzM19vdXQgPC0gZmlsZS5wYXRoKGRhdGFfZGlyLCAiZGF0YSIsICJxdWFudHMiKQoKIyByZXN1bHRzIGRpcmVjdG9yeSAKcmVzdWx0c19kaXIgPC0gZmlsZS5wYXRoKGRhdGFfZGlyLCAicmVzdWx0cyIpCgojIGNyZWF0ZSBkaXJlY3RvcmllcwppZighZGlyLmV4aXN0cyhkYXRhX2RpcikpewogIGRpci5jcmVhdGUoZGF0YV9kaXIsIHJlY3Vyc2l2ZSA9IFRSVUUpCn0KCmlmKCFkaXIuZXhpc3RzKHJlc3VsdHNfZGlyKSl7CiAgZGlyLmNyZWF0ZShyZXN1bHRzX2RpciwgcmVjdXJzaXZlID0gVFJVRSkKfQpgYGAKCgpgYGB7cn0KbWl0b19maWxlIDwtIGZpbGUucGF0aChiYXNlX2RpciwgInNhbXBsZS1pbmZvIiwgIkhvbW9fc2FwaWVucy5HUkNoMzguMTAzLm1pdG9nZW5lcy50eHQiKQogIAojIHJlYWQgaW4gbWl0byBnZW5lcyAKbWl0b19nZW5lcyA8LSByZWFkcjo6cmVhZF90c3YobWl0b19maWxlLCBjb2xfbmFtZXMgPSAiZ2VuZV9pZCIpCm1pdG9fZ2VuZXMgPC0gbWl0b19nZW5lcyAlPiUKICBkcGx5cjo6cHVsbChnZW5lX2lkKSAlPiUKICB1bmlxdWUoKQpgYGAKCiMjIENvcHkgZGF0YSBmcm9tIFMzCgpgYGB7cn0KIyBzZXQgc2FtcGxlcyB0byBwcm9jZXNzCnNhbXBsZV9pZCA8LSBjKCJTQ1BDUjAwMDM3MiIpCmBgYAoKYGBge3IgZXZhbD1GQUxTRX0KIyBkb3dubG9hZCBhbGV2aW4gZnJ5IGFuZCBjZWxscmFuZ2VyIG91dHB1dAphd3NfY29weV9zYW1wbGVzKGxvY2FsX2RpciA9IHMzX291dCwKICAgICAgICAgICAgICAgICBzM19kaXIgPSAiczM6Ly9uZXh0Zmxvdy1jY2RsLXJlc3VsdHMvc2NwY2EiLAogICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzYW1wbGVfaWQsCiAgICAgICAgICAgICAgICAgdG9vbHMgPSBjKCJhbGV2aW4tZnJ5LWtuZWUiLCAiY2VsbHJhbmdlciIpKQpgYGAKCiMjIENvbXBhcmluZyBTcGF0aWFsRXhwZXJpbWVudCB0byBTZXVyYXQKCiMjIyBJbXBvcnRpbmcgQWxldmluLWZyeSBhbmQgU3BhY2VyYW5nZXIgb3V0cHV0IGludG8gYSBTcGF0aWFsRXhwZXJpbWVudAoKRmlyc3Qgd2UgYXJlIHRlc3RpbmcgdXNlIG9mIGEgYFNwYXRpYWxFeHBlcmltZW50YCBvYmplY3QgdG8gc3RvcmUgdGhlIHNwYXRpYWwgdHJhbnNjcmlwdG9taWNzIHJlc3VsdHMuIApXZSB3aWxsIGxvb2sgYXQgdGhlIEFsZXZpbi1mcnkgKyBTcGFjZXJhbmdlciBxdWFudGlmaWNhdGlvbiBhbmQgdXNlIGEgY3VzdG9tIGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgY29tYmluZWQgb2JqZWN0IGZyb20gYm90aCB0b29scy4KCmBgYHtyfQojIGdldCBwYXRoIHRvIGZyeSBvdXRwdXQgZGlyZWN0b3J5IApmcnlfZGlyIDwtIGZpbGUucGF0aChzM19vdXQsICJhbGV2aW4tZnJ5LWtuZWUiLCBzYW1wbGVfaWQpCmZyeV9kaXIgPC0gcGFzdGUwKGZyeV9kaXIsICItc3BsaWNlZF9pbnRyb25fdHhvbWVfazMxLXNhbGlnbi1jci1saWtlLWVtLWtuZWUiKQoKIyBwYXRocyB0byBzcGF0aWFsIGZvbGRlcnMgCmNlbGxyYW5nZXJfZm9sZGVyIDwtIHBhc3RlMChzYW1wbGVfaWQsICItY2RuYS1zcGF0aWFsIikKc3BhdGlhbF9kaXIgPC0gZmlsZS5wYXRoKHMzX291dCwgImNlbGxyYW5nZXIiLCBjZWxscmFuZ2VyX2ZvbGRlciwgIm91dHMiLCAic3BhdGlhbCIpCmBgYAoKYGBge3J9CiMgcmVhZCBpbiBjb21iaW5lZCBmcnkgYW5kIHNwYWNlcmFuZ2VyIHNwZSAKZnJ5X3NwZSA8LSBjcmVhdGVfZnJ5X3NwYWNlcmFuZ2VyX3NwZShmcnlfZGlyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhdGlhbF9kaXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfaWQpCmBgYAoKIyMjIEltcG9ydGluZyBhcyBTZXVyYXQgT2JqZWN0CgpCZWxvdyB3ZSB3aWxsIGltcG9ydCB0aGUgc2FtZSBkYXRhIGJ1dCBhcyBhIGBTZXVyYXRgIG9iamVjdCBpbnN0ZWFkIG9mIGEgYFNwYXRpYWxFeHBlcmltZW50YCBvYmplY3QuIAoKYGBge3J9CiMgZmlyc3QgY3JlYXRlIHNjZSBmcm9tIEFsZXZpbiBvdXRwdXQKZnJ5X3NjZSA8LSBzY3BjYVRvb2xzOjpyZWFkX2FsZXZpbihmcnlfZGlyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYV9tb2RlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGljaF9jb3VudHMgPSAic3BsaWNlZCIpCgojIGNvbnZlcnQgc2NlIHRvIHNldXJhdCBvYmplY3QgCmZyeV9zZXVyYXQgPC0gU2V1cmF0OjpDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gY291bnRzKGZyeV9zY2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9qZWN0ID0gIlNQQVRJQUwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheSA9ICJTcGF0aWFsIikKCiMgcmVhZCBpbiBpbWFnZSBkYXRhIHVzaW5nIFNldXJhdCBhbmQgc3Vic2V0IHRvIGNvbW1vbiBjZWxscwppbWFnZV9kYXRhIDwtIFNldXJhdDo6UmVhZDEwWF9JbWFnZShzcGF0aWFsX2RpcikKcm93bmFtZXMoaW1hZ2VfZGF0YUBjb29yZGluYXRlcykgPC0gZ3N1YigiLTEiLCIiLCByb3duYW1lcyhpbWFnZV9kYXRhQGNvb3JkaW5hdGVzKSkKY29tbW9uX2NlbGxzIDwtIGludGVyc2VjdChTZXVyYXQ6OkNlbGxzKHggPSBmcnlfc2V1cmF0KSwgcm93bmFtZXMoaW1hZ2VfZGF0YUBjb29yZGluYXRlcykpCmltYWdlX2RhdGEgPC0gaW1hZ2VfZGF0YVtjb21tb25fY2VsbHMsXQoKIyBhZGQgaW1hZ2UgZGF0YSB0byBTZXVyYXQKU2V1cmF0OjpEZWZhdWx0QXNzYXkob2JqZWN0ID0gaW1hZ2VfZGF0YSkgPC0gIlNwYXRpYWwiCmZyeV9zZXVyYXRbWydzbGljZSddXSA8LSBpbWFnZV9kYXRhCmBgYAoKCiMjIyBDb21wYXJpbmcgU2V1cmF0IGFuZCBTcGF0aWFsIEV4cGVyaW1lbnQKCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCBob3cgZWFjaCBvZiB0aGVzZSBvYmplY3RzIHN0b3JlcyBpbmZvcm1hdGlvbiBmb3IgdGhlIGV4cGVyaW1lbnQuIAoKYGBge3J9CmhlYWQoY29sRGF0YShmcnlfc3BlKSkKaGVhZChmcnlfc2V1cmF0QG1ldGEuZGF0YSkKYGBgCgpTZXVyYXQgYXV0b21hdGljYWxseSBhZGRzIHNvbWUgcGVyIGNlbGwgUUMgbWV0cmljcyBoZXJlLCBidXQgaW4gZ2VuZXJhbCB0aGUgYGNvbERhdGFgIGxvb2tzIHNpbWlsYXIgdG8gd2hhdCB3ZSB3b3VsZCBleHBlY3QgZm9yIGEgYFNpbmdsZUNlbGxFeHBlcmltZW50YCBmb3IgdGhlIGBTcGF0aWFsRXhwZXJpbWVudGAuCgpgYGB7cn0KaGVhZChyb3dEYXRhKGZyeV9zcGUpKQpoZWFkKGZyeV9zZXVyYXRbWyJTcGF0aWFsIl1dQG1ldGEuZmVhdHVyZXMpCmBgYAoKSXQgbG9va3MgbGlrZSBib3RoIG9mIHRoZXNlIHN0YXJ0IG9mZiB3aXRoIG5vIGByb3dEYXRhYCBhcyBleHBlY3RlZC4KCmBgYHtyfQpmcnlfc3BlIDwtIGZyeV9zcGUgJT4lCiAgc2N1dHRsZTo6YWRkUGVyQ2VsbFFDTWV0cmljcyhzdWJzZXRzID0gbGlzdChtaXRvX2dlbmVzID0gbWl0b19nZW5lc1ttaXRvX2dlbmVzICVpbiUgcm93bmFtZXMoZnJ5X3NwZSldKSkgCmhlYWQoY29sRGF0YShmcnlfc3BlKSkKYGBgCgpZb3UgY2FuIHN0aWxsIHVzZSB0aGUgc2FtZSBmdW5jdGlvbnMgdG8gYWRkIGluIHBlciBjZWxsIG1ldHJpY3MgdGhhdCB3ZSBhcmUgdXNpbmcgaW4gYHNjcGNhVG9vbHNgIG5vdyBvbiBhIGBTcGF0aWFsRXhwZXJpbWVudGAuIAoKTGV0J3Mgc3BlY2lmaWNhbGx5IGxvb2sgYXQgaG93IGVhY2ggb2YgdGhlbSBzdG9yZXMgdGhlIGRhdGEgcmVsYXRlZCB0byB0aGUgc3BhdGlhbCBpbmZvcm1hdGlvbi4KVGhlIGBTcGF0aWFsRXhwZXJpbWVudGAgaGFzIHRocmVlIHBsYWNlcyB3aGVyZSBpdCBzdG9yZXMgc3BhdGlhbCBpbmZvcm1hdGlvbiwgYHNwYXRpYWxEYXRhYCwgYHNwYXRpYWxDb29yZHNgLCBhbmQgYGltZ0RhdGFgLiAKCmBgYHtyfQpoZWFkKHNwYXRpYWxEYXRhKGZyeV9zcGUpKQpgYGAKCmBgYHtyfQpoZWFkKHNwYXRpYWxDb29yZHMoZnJ5X3NwZSkpCmBgYAoKYHNwYXRpYWxEYXRhYCBob2xkcyBpbmZvcm1hdGlvbiBhYm91dCB3aGV0aGVyIG9yIG5vdCBlYWNoIGJhcmNvZGUgd2FzIGNvdmVyZWQgYnkgdGlzc3VlIGFuZCBzcGF0aWFsIG1ldGFkYXRhLgpgc3BhdGlhbENvb3Jkc2AgaG9sZHMgdGhlIGNvb3JkaW5hdGVzIGZvciBlYWNoIHNwb3QuCgpUaGlzIHNhbWUgaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIGJ5IGxvb2tpbmcgaW4gdGhlIGBpbWFnZXNgIHNsb3QgaW4gdGhlIGBTZXVyYXRgIG9iamVjdC4gCgpgYGB7cn0KaGVhZChmcnlfc2V1cmF0QGltYWdlcykKYGBgCgpgaW1nRGF0YWAgaG9sZHMgaW5mb3JtYXRpb24gYWJvdXQgZWFjaCBpbWFnZSB0aGF0IGlzIHN0b3JlZCBhcyBtdWx0aXBsZSBzbGljZXMgb2YgYW4gaW1hZ2UgY2FuIGJlIHN0b3JlZCB3aXRoaW4gb25lIGBTcGF0aWFsRXhwZXJpbWVudGAuIAoKYGBge3J9CmltZ0RhdGEoZnJ5X3NwZSkKYGBgCgpUaGlzIHNhbWUgaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIGJ5IGxvb2tpbmcgYXQgdGhlIGBpbWFnZXNgIHNsb3QgaW4gdGhlIGBTZXVyYXRgIG9iamVjdC4gCgpgYGB7cn0KZnJ5X3NldXJhdEBpbWFnZXMkc2xpY2VAc2NhbGUuZmFjdG9ycwpgYGAKCkxldCdzIHRha2UgYSBsb29rIGF0IHNvbWUgZXhhbXBsZSBwbG90cyB0aGF0IGNhbiBiZSBwcm9kdWNlZCB3aXRoIGVhY2ggb2YgdGhlc2Ugb2JqZWN0cy4KCmBgYHtyfQpsaWJyYXJ5KHZpcmlkaXMpCiMgcGxvdCB0aXNzdWUgc3BvdHMgY29sb3JpbmcgYnkgdG90YWwgVU1JIGNvdW50Cmdnc3BhdmlzOjpwbG90U3BvdHMoc3BlID0gZnJ5X3NwZSwgCiAgICAgICAgICB4X2Nvb3JkID0gInB4bF9jb2xfaW5fZnVsbHJlcyIsIAogICAgICAgICAgeV9jb29yZCA9ICJweGxfcm93X2luX2Z1bGxyZXMiLCAKICAgICAgICAgIGFubm90YXRlID0gInN1bSIpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKQpgYGAKWW91IGNhbiBhbHNvIG92ZXJsYXkgdGhlIGltYWdlIGJ5IHVzaW5nIGBwbG90VmlzaXVtYC4gCgpgYGB7cn0KZ2dzcGF2aXM6OnBsb3RWaXNpdW0oc3BlID0gZnJ5X3NwZVssc3BhdGlhbERhdGEoZnJ5X3NwZSkkaW5fdGlzc3VlID09IDFdLAogICAgICAgICAgICAgICAgICAgICB4X2Nvb3JkID0gInB4bF9jb2xfaW5fZnVsbHJlcyIsCiAgICAgICAgICAgICAgICAgICAgIHlfY29vcmQgPSAicHhsX3Jvd19pbl9mdWxscmVzIikKYGBgCgpgYGB7cn0KU2V1cmF0OjpTcGF0aWFsRmVhdHVyZVBsb3QoZnJ5X3NldXJhdCwgZmVhdHVyZXMgPSAibkNvdW50X1NwYXRpYWwiKQpgYGAKCkl0IGxvb2tzIGxpa2Ugb3ZlcmFsbCB0aGV5IGJvdGggd291bGQgd29yayBhbmQgdGhhdCB0aGUgYFNwYXRpYWxFeHBlcmltZW50YCB3aWxsIHByb3ZpZGUgc2ltaWxhciBmdW5jdGlvbmFsaXR5IHRvIGhvdyB3ZSBoYXZlIHRoaW5ncyBhbHJlYWR5IHNldCB1cCBmb3Igc2luZ2xlLWNlbGwgZXhwZXJpbWVudHMuIAoKT25lIHRoaW5nIHRvIG5vdGUgaXMgdGhhdCB0aGVyZSBpcyBpbmNvbXBhdGliaWxpdHkgYmV0d2VlbiBgU3BhdGlhbEV4cGVyaW1lbnRgIGFuZCBgU2V1cmF0YCwgYW5kIHRoaXMgbm90ZWJvb2sgd2lsbCBub3QgcnVuIHRvIGNvbXBsZXRpb24gYmVjYXVzZSBvZiB0aGlzLiAKVGhlIGxhc3QgY2h1bmsgd2hpY2ggaW5jbHVkZXMgbWFraW5nIHRoZSBwbG90IHVzaW5nIGBTZXVyYXRgIGhhcyBhIGNvbmZsaWN0IHdpdGggdGhlIGBpbWdSYXN0ZXJgIGZ1bmN0aW9uIHByZXNlbnQgaW4gYm90aCBgU2V1cmF0YCBhbmQgYFNwYXRpYWxFeHBlcmltZW50YCB0aGF0IHdpbGwgY2F1c2UgdGhpcyBjaHVuayB0byBmYWlsLiAKVGhlIHdheSB0byByZW1vdmUgdGhpcyBlcnJvciBpcyB0byB1bmluc3RhbGwgdGhlIGBTcGF0aWFsRXhwZXJpbWVudGAgcGFja2FnZSBhbmQgdGhlbiByZWluc3RhbGwgYFNldXJhdGAuClRoaXMgaXMgZG9jdW1lbnRlZCBpbiBbYW4gaXNzdWUgb24gdGhlIGBTZXVyYXRgIHJlcG9dKGh0dHBzOi8vZ2l0aHViLmNvbS9zYXRpamFsYWIvc2V1cmF0L2lzc3Vlcy81MTI4KS4gCgpBZGRpdGlvbmFsbHksIHRoZXJlIHdpbGwgYmUgd2FybmluZ3MgdGhyb3VnaG91dCB0aGUgbm90ZWJvb2sgdGhhdCBib3RoIHBhY2thZ2VzIHJlZmVyIHRvIGBTcGF0aWFsSW1hZ2VgLCBhbmQgYnkgZGVmYXVsdCBpdCB3aWxsIGFsd2F5cyB1c2UgYFNldXJhdGAsIGhvd2V2ZXIgdGhvc2UgY2h1bmtzIHdpbGwgc3RpbGwgcnVuLiAKVGhpcyBlcnJvciBhcHBlYXJzIHRvIG9jY3VyIGV2ZW4gd2l0aG91dCBsb2FkaW5nIGBTZXVyYXRgLgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgo=